package com.custom.floatlove;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.Random;

/**
 * @description：TODO
 * @Author MRyan
 * @Date 2020/3/10 20:00
 * @Version 1.0
 */
public class FloatLove extends View {
    private static final String LOG = "FloatLove";
    private Bitmap mbitmap;//绘制心
    private Paint mRoutePaint;//绘制贝塞尔曲线
    private Path mpath;//绘制贝塞尔曲线
    private int wight;
    private int height;
    private int bapwidht;
    private int bapheight;

    //记录数据点，控制点(由于是三阶贝塞尔曲线，所以有2个控制点)
    private Point mStartPoint;//贝塞尔曲线初始固定点
    private Point mEndPoint;//贝塞尔曲线结束固定点
    private Point mConOnePoint;//贝塞尔曲线左控制点
    private Point mConTwoPoint;//贝塞尔曲线右控制点
    private Point value;
    @SuppressLint("DrawAllocation")
    private Bitmap bitmap;
    private float alpha = 255;
    private ValueAnimator valueAnimator;

    private Random random;
    private int offest;//偏移量
    private int offestplusorminus;//偏移量正负

    public FloatLove(Context context) {
        super(context);
        initAttr();
        initPatin();
    }

    public FloatLove(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initAttr();
        initPatin();
    }

    private void initAttr() {
        mStartPoint = new Point();
        mEndPoint = new Point();
        mConOnePoint = new Point();
        mConTwoPoint = new Point();
        value = new Point();

    }

    public FloatLove(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttr();
        initPatin();
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        wight = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(wight, height);
        random = new Random();
        mStartPoint.x = wight / 2;
        mStartPoint.y = height;
        mEndPoint.x = wight / 2;
        mEndPoint.y = 0;

        mConOnePoint.x = wight;
        mConOnePoint.y = height * 3 / 4;

        mConTwoPoint.x = 0;
        mConTwoPoint.y = height / 4;

        //随机数控制心出现的位置
        offestplusorminus = random.nextInt(2);
        Log.e(LOG, offestplusorminus + "");
        if (offestplusorminus == 1) {//位移为正
            offest = random.nextInt(200);
            Log.e(LOG, "正");
        } else {//位移为负
            int minus = random.nextInt(200);
            Log.e(LOG, "负");
            offest = -minus;
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        drawLove(canvas);
    }

    public void drawLove(Canvas canvas) {
        mRoutePaint.setAlpha((int) alpha);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.love);
        bapwidht = bitmap.getWidth();
        bapheight = bitmap.getHeight();
        Matrix matrix = new Matrix();
        matrix.postTranslate(wight - value.x - offest, height - value.y);//高度不需要减bitmap本身高度，初始不用漏出心，否则会出现位移BUG
        canvas.drawBitmap(bitmap, matrix, mRoutePaint);
        //绘制贝塞尔曲线
        mpath.reset();
        mpath.moveTo(mEndPoint.x - offest, mEndPoint.y);//初始点 从下往上 贝塞尔曲线终止点为起始点
        mpath.cubicTo(mConOnePoint.x - offest, mConOnePoint.y, mConTwoPoint.x - offest, mConTwoPoint.y, mStartPoint.x - offest, mStartPoint.y);//控制点 和终止点
        /* canvas.drawPath(mpath, mRoutePaint);*/
        canvas.save();
    }

    public void addStar() {
        //设置属性动画
        valueAnimator = ValueAnimator.ofObject(new StarTypeEvaluator(mConOnePoint, mConTwoPoint), mEndPoint,
                mStartPoint);
        valueAnimator.setDuration(6000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point point = (Point) animation.getAnimatedValue();
                value.x = point.x;
                value.y = point.y;
                if (point.y >= height / 2) {
                    alpha -= 4;//透明度不断减少
                }
                if (alpha < 0) {
                    alpha = 0;
                }
                postInvalidate();
            }
        });
        valueAnimator.start();//开始动画
        //监听动画结束
       /* valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                alpha = 255;//透明度重置
                //0，1，2随机数
                offestplusorminus = random.nextInt(2);
                if (offestplusorminus == 1) {//位移为正
                    offest = random.nextInt(200);
                } else {//位移为负
                    int minus = random.nextInt(200);
                    offest = -minus;
                }
                postInvalidate();
            }
        });*/


    }


    //动画估值器
    class StarTypeEvaluator implements TypeEvaluator<Point> {

        //记录控制点
        private Point conOnePoint, conSecondPoint;

        public StarTypeEvaluator(Point conOnePoint, Point conSecondPoint) {
            this.conOnePoint = conOnePoint;
            this.conSecondPoint = conSecondPoint;
        }

        @Override
        public Point evaluate(float t, Point startValue, Point endValue) {

            //利用三阶贝塞尔曲线公式算出中间点坐标
            int x = (int) (startValue.x * Math.pow((1 - t), 3) + 3 * conOnePoint.x * t * Math.pow((1 - t), 2) + 3 *
                    conSecondPoint.x * Math.pow(t, 2) * (1 - t) + endValue.x * Math.pow(t, 3));
            int y = (int) (startValue.y * Math.pow((1 - t), 3) + 3 * conOnePoint.y * t * Math.pow((1 - t), 2) + 3 *
                    conSecondPoint.y * Math.pow(t, 2) * (1 - t) + endValue.y * Math.pow(t, 3));
            return new Point(x, y);
        }
    }


    private void initPatin() {
        mpath = new Path();
        mRoutePaint = new Paint();
        mRoutePaint.setAntiAlias(true);
        mRoutePaint.setColor(Color.RED);
        mRoutePaint.setAlpha(0);
        mRoutePaint.setStrokeWidth(20);
        mRoutePaint.setStyle(Paint.Style.STROKE);
    }


}
